package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.UserDataIsolation;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.ProductPropertyValueResultVO;
import com.ruoyi.system.domain.vo.ProductPropertyValueVO;
import com.ruoyi.system.domain.vo.QueryVo;
import com.ruoyi.system.mapper.PointCheckMapper;
import com.ruoyi.system.mapper.ProjectDeviceGroupMapper;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PointCheckServiceImpl implements IPointCheckService {
    @Autowired
    private PointCheckMapper pointCheckMapper;
    @Autowired
    private IPointCheckDateService pointCheckDateService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IPointCheckTaskService pointCheckTaskService;

    @Autowired
    private ProjectDeviceGroupMapper projectDeviceGroupMapper;
    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private IPointCheckConfigService pointCheckConfigService;

    @Autowired
    private IProjectDeviceGroupService projectDeviceGroupService;


    /**
     * 定时任务执行flag
     */
    @Value("${scheduledTask.flag:false}")
    private boolean scheduledTaskFlag;

    /**
     * 现场工程师
     */
    @Value("${sysUser.sceneRoleId:102}")
    private Long sceneRoleId;

    /**
     * 巡检工角色Id
     */
    @Value("${sysUser.inspectorRoleId:104}")
    private Long inspectorRoleId;

    @Override
    @UserDataIsolation(tableAlias = "pc")
    public List<PointCheck> queryList(PointCheck pointCheck) {
        List<PointCheck> pointChecks = pointCheckMapper.queryList(pointCheck);
        if (CollUtil.isNotEmpty(pointChecks)){
            pointChecks.forEach(a ->{
                //获取用户昵称
                SysUser sysUser = sysUserService.selectUserByUserName(a.getExecutor());
                if (sysUser != null){
                    a.setNickName(sysUser.getNickName());
                }
            });
        }
        return pointChecks;
    }

    @Override
    public List<PointCheck> queryGroupList(PointCheck pointCheck) {
        return pointCheckMapper.queryGroupList(pointCheck);
    }


    @Override
    @UserDataIsolation(tableAlias = "pc")
    public PointCheck getOne(PointCheck pointCheck) {
        PointCheck result = pointCheckMapper.getOne(pointCheck);
        if (result == null) {
            return null;
        }
        //获取用户昵称
        SysUser sysUser = sysUserService.selectUserByUserName(result.getExecutor());
        if (sysUser != null){
            result.setNickName(sysUser.getNickName());
        }
        //TODO 获取计划时间
        Integer pointId = result.getId();
        PointCheckDate pointCheckDate = new PointCheckDate();
        pointCheckDate.setPointId(pointId);
        List<PointCheckDate> pointCheckDates = pointCheckDateService.queryList(pointCheckDate);
        if (CollUtil.isNotEmpty(pointCheckDates)) {
            result.setPointCheckDates(pointCheckDates);
        }
        return result;
    }

    @Override
    @Transactional
    public Boolean add(PointCheck pointCheck) {
        int add = pointCheckMapper.add(pointCheck);
        if(add>0){
            Boolean aBoolean = addPointCheckConfig(pointCheck);
            return aBoolean;

        }


        return false;
    }

    private Boolean addPointCheckConfig(PointCheck pointCheck) {
        Integer pointId = pointCheck.getId();
        Long companyId = pointCheck.getCompanyId();
        String createBy = pointCheck.getCreateBy();
        Date createTime = pointCheck.getCreateTime();
        HashMap<String, ArrayList<Integer>> checkConfigList = pointCheck.getCheckConfigList();
        for (Map.Entry<String, ArrayList<Integer>> checkConfig : checkConfigList.entrySet()) {
            Integer deviceId = Integer.parseInt(checkConfig.getKey());
            ArrayList<Integer> list = checkConfig.getValue();
            for (Integer i : list
            ) {
                Integer checkConfigId = i;
                PointCheckConfig pointCheckConfig = new PointCheckConfig();
                pointCheckConfig.setPointId(pointId);
                pointCheckConfig.setDeviceId(deviceId);
                pointCheckConfig.setCheckConfigId(checkConfigId);
                pointCheckConfig.setCompanyId(companyId);
                pointCheckConfig.setCreateBy(createBy);
                pointCheckConfig.setCreateTime(createTime);
                Boolean add1 = pointCheckConfigService.add(pointCheckConfig);
                if(!add1){
                    return false;
                }

            }

        }
        return true;
    }

    @Override
    @UserDataIsolation
    @Transactional
    public Boolean update(PointCheck pointCheck) {
        int update = pointCheckMapper.update(pointCheck);
        if(update>0){
            Integer pointId = pointCheck.getId();
            Boolean delete = pointCheckConfigService.deletePointId(pointId);
            if(!delete){
                throw new CustomException("修改失败");
            }
            Boolean aBoolean = addPointCheckConfig(pointCheck);
            return aBoolean;
        }

        return false;
    }
    public Boolean updateInfo(PointCheck pointCheck) {
        return pointCheckMapper.update(pointCheck)>0;
    }

    @Override
    @UserDataIsolation
    @Transactional
    public Boolean delete(PointCheck pointCheck) {
        if (pointCheckMapper.delete(pointCheck) > 0) {
            PointCheckDate pointCheckDate = new PointCheckDate();
            pointCheckDate.setPointId(pointCheck.getId());
            pointCheckDateService.delete(pointCheckDate);
            return true;
        }
        return false;
    }

    @Override
    @UserDataIsolation
    public void checkIsExist(PointCheck pointCheck) {
        PointCheck isExist = pointCheckMapper.checkIsExist(pointCheck);
        if (isExist == null) {
            return;
        }
        if (pointCheck.getId() == null || isExist.getId().compareTo(pointCheck.getId()) != 0) {
            throw new CustomException("该计划名称和系统已存在");
        }
    }

    /**
     * 验证添加指派人角色权限
     * 客户只能添加巡检工角色用户
     * 非客户只能添加现场工程师角色用户
     *
     * @param pointCheck
     */
    @Override
    public void checkExecutorStatus(PointCheck pointCheck){
        String executor = pointCheck.getExecutor();
        SysUser sysUser = sysUserService.selectUserByUserName(executor);
        if (sysUser == null){
            throw new CustomException("没有查询到指派人用户信息");
        }
        SysRole roles = sysUser.getRoles().get(0);
        Long deptId = SecurityUtils.getLoginUser().getUser().getDeptId();
        if (sysDeptService.checkIsCustomer(deptId)){
            if (roles.getRoleId().compareTo(inspectorRoleId) != 0){
                throw new CustomException("当前用户只能添加巡检工角色用户");
            }
        }else {
            if (roles.getRoleId().compareTo(sceneRoleId) != 0){
                throw new CustomException("当前用户只能添加现场工程师角色用户");
            }
        }
    }

    @Override
    @Transactional
    public void addPointCheckDate(PointCheck pointCheck) {
        Integer pointId = pointCheck.getId();
        if (pointId == null) {
            throw new CustomException("计划Id不能为空");
        }
        //获取需要操作的数据
        List<PointCheckDate> updateDates = pointCheck.getPointCheckDates();
        if (CollUtil.isNotEmpty(updateDates)) {
            updateDates.forEach(a -> {
                a.setPointId(pointId);
                if (a.getId() == null) {
                    a.setCompanyId(pointCheck.getCompanyId());
                    a.setCreateBy(pointCheck.getCreateBy());
                    a.setCreateTime(new Date());
                }
            });
        }
        PointCheckDate pointCheckDate = new PointCheckDate();
        pointCheckDate.setPointId(pointId);
        List<PointCheckDate> pointCheckDates = pointCheckDateService.queryList(pointCheckDate);
        if (CollUtil.isEmpty(pointCheckDates)) {
            if (CollUtil.isNotEmpty(updateDates)) {
                //新增
                updateDates.forEach(a -> {
                    pointCheckDateService.add(a);
                });
            }
            return;
        }
        //数据库中有数据
        if (CollUtil.isEmpty(updateDates)) {
            //需要删除
            updateDates.forEach(a -> {
                pointCheckDateService.delete(a);
            });
            return;
        }
        //修改后的计划id
        Set<Integer> updateIds = updateDates.stream().map(PointCheckDate::getId).collect(Collectors.toSet());
        //删除修改后不存在的计划id
        pointCheckDates.forEach(a -> {
            if (!updateIds.contains(a.getId())) {
                pointCheckDateService.delete(a);
            }
        });
        //进行新增或修改
        updateDates.forEach(a -> {
            if (a.getId() == null) {
                pointCheckDateService.add(a);
            } else {
                pointCheckDateService.update(a);
            }
        });
    }

    @Override
    public List<Map<String, Object>> queryUserInfo(QueryVo queryVo) {
        return pointCheckMapper.queryUserInfo(queryVo);
    }

    @Override
    @Scheduled(cron = "0 30 02 * * ?")
    public void createPointCheckTask() {
        if (!scheduledTaskFlag){
            return;
        }
        String todayStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        // 获取当天是周几
        /*
            工具类是从周日开始算的，周日返回1，周一返回2
         */
        int nowDay = DateUtil.dayOfWeek(new Date()) == 1 ? 7 : DateUtil.dayOfWeek(new Date()) - 1;
        //获取点检计划
        PointCheck pointCheck = new PointCheck();
        pointCheck.setStatus("1");
        List<PointCheck> pointChecks = pointCheckMapper.queryList(pointCheck);
        if (CollUtil.isEmpty(pointChecks)){
            return;
        }
        List<PointCheckTask> pointCheckTasks = new ArrayList<>();
        for (PointCheck check : pointChecks) {
            //查询该计划的时间
            Integer id = check.getId();
            PointCheckDate param = new PointCheckDate();
            param.setPointId(id);
            List<PointCheckDate> pointCheckDates = pointCheckDateService.queryList(param);
            if (CollUtil.isEmpty(pointCheckDates)){
                continue;
            }
            for (PointCheckDate checkDate : pointCheckDates) {
                String start = checkDate.getStart();
                String end = checkDate.getEnd();
                String weekday = checkDate.getWeekday();
                List<String> weekdayList = StrUtil.splitTrim(weekday, ",");
                if (!weekdayList.contains(Convert.toStr(nowDay))){
                    continue;
                }
                //生成任务
                PointCheckTask task = new PointCheckTask();
                String startTimeStr = todayStr + " " + start;
                String endTimeStr = todayStr + " " + end;
                task.setCompanyId(checkDate.getCompanyId());
                task.setEndTime(DateUtil.parse(endTimeStr,"yyyy-MM-dd HH:mm","yyyy-MM-dd HH:mm:ss"));
                task.setStartTime(DateUtil.parse(startTimeStr,"yyyy-MM-dd HH:mm","yyyy-MM-dd HH:mm:ss"));
                task.setStatus("0");
                task.setCategory(0);
                task.setCreateTime(new Date());
                task.setExecutor(check.getExecutor());
                task.setProjectId(check.getProjectId());
                task.setGroupId(check.getGroupId());
                task.setName(check.getName());



                //获取分组的任务
                Integer groupId = check.getGroupId();
                ProjectDeviceGroup projectDeviceGroup = projectDeviceGroupService.selectTblProjectDeviceGroupById(groupId);
                List<Device> deviceList = projectDeviceGroup.getDeviceList();
                ArrayList<Integer> deviceIds = new ArrayList<>();
                HashMap<String,ArrayList<Integer>> checkConfigList = new HashMap<>();
                for (Device d:deviceList
                ) {
                    deviceIds.add(d.getId());
                    PointCheckConfig pointCheckConfig = new PointCheckConfig();
                    pointCheckConfig.setPointId(id);
                    pointCheckConfig.setDeviceId(d.getId());
                    List<PointCheckConfig> pointCheckConfigs = pointCheckConfigService.queryList(pointCheckConfig);
                    ArrayList<Integer> integers = new ArrayList<>();
                    for (PointCheckConfig pcc: pointCheckConfigs
                    ) {
                        integers.add(pcc.getCheckConfigId());
                    }
                    checkConfigList.put(d.getId()+"",integers);


                }
                task.setCheckConfigList(checkConfigList);
                task.setDeviceIds(StringUtils.join(deviceIds.toArray(), ','));

                //获取点检配置

                pointCheckTasks.add(task);
            }
        }
        log.info("生成的任务{}",pointCheckTasks);
        //进行保存操作
        for (PointCheckTask task : pointCheckTasks) {
            List<Device> devices = projectDeviceGroupMapper.getDeviceByGroupId(task.getGroupId());
            if (CollUtil.isNotEmpty(devices)){
                List<Integer> deviceIds = devices.stream().map(Device::getId).collect(Collectors.toList());
                task.setDeviceIds(StrUtil.join(",", deviceIds));
            }
            task.setCategory(0);
            pointCheckTaskService.addV2(task);
        }
    }

    @Override
    public Boolean getTask(PointCheck pointCheck) {
        List<PointCheckTask> pointCheckTasks = new ArrayList<>();
        String todayStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        int nowDay = DateUtil.dayOfWeek(new Date()) == 1 ? 7 : DateUtil.dayOfWeek(new Date()) - 1;

        PointCheck check = pointCheckMapper.getOne(pointCheck);
        Integer id = pointCheck.getId();
        PointCheckDate param = new PointCheckDate();
        param.setPointId(id);
        List<PointCheckDate> pointCheckDates = pointCheckDateService.queryList(param);
        for (PointCheckDate checkDate : pointCheckDates) {
            String start = checkDate.getStart();
            String end = checkDate.getEnd();
            String weekday = checkDate.getWeekday();
            List<String> weekdayList = StrUtil.splitTrim(weekday, ",");
            if (!weekdayList.contains(Convert.toStr(nowDay))){
                continue;
            }
            //生成任务
            PointCheckTask task = new PointCheckTask();
            String startTimeStr = todayStr + " " + start;
            String endTimeStr = todayStr + " " + end;
            task.setCompanyId(checkDate.getCompanyId());
            task.setEndTime(DateUtil.parse(endTimeStr,"yyyy-MM-dd HH:mm","yyyy-MM-dd HH:mm:ss"));
            task.setStartTime(DateUtil.parse(startTimeStr,"yyyy-MM-dd HH:mm","yyyy-MM-dd HH:mm:ss"));
            task.setStatus("0");
            task.setCategory(0);
            task.setCreateTime(new Date());
            task.setExecutor(check.getExecutor());
            task.setProjectId(check.getProjectId());
            task.setGroupId(check.getGroupId());
            task.setName(check.getName());



            //获取分组的任务
            Integer groupId = check.getGroupId();
            ProjectDeviceGroup projectDeviceGroup = projectDeviceGroupService.selectTblProjectDeviceGroupById(groupId);
            List<Device> deviceList = projectDeviceGroup.getDeviceList();
            ArrayList<Integer> deviceIds = new ArrayList<>();
            HashMap<String,ArrayList<Integer>> checkConfigList = new HashMap<>();
            for (Device d:deviceList
            ) {
                deviceIds.add(d.getId());
                PointCheckConfig pointCheckConfig = new PointCheckConfig();
                pointCheckConfig.setPointId(id);
                pointCheckConfig.setDeviceId(d.getId());
                List<PointCheckConfig> pointCheckConfigs = pointCheckConfigService.queryList(pointCheckConfig);
                ArrayList<Integer> integers = new ArrayList<>();
                for (PointCheckConfig pcc: pointCheckConfigs
                ) {
                    integers.add(pcc.getCheckConfigId());
                }
                checkConfigList.put(d.getId()+"",integers);


            }
            task.setCheckConfigList(checkConfigList);
            task.setDeviceIds(StringUtils.join(deviceIds.toArray(), ','));

            //获取点检配置

            pointCheckTasks.add(task);
        }

        //进行保存操作
        for (PointCheckTask task : pointCheckTasks) {
            List<Device> devices = projectDeviceGroupMapper.getDeviceByGroupId(task.getGroupId());
            if (CollUtil.isNotEmpty(devices)){
                List<Integer> deviceIds = devices.stream().map(Device::getId).collect(Collectors.toList());
                task.setDeviceIds(StrUtil.join(",", deviceIds));
            }
            task.setCategory(0);
            pointCheckTaskService.addV2(task);
        }

        return true;
    }

    @Override
    @UserDataIsolation
    public List<Map<String, String>> queryAuthorizeEnum(QueryVo queryVo) {
        return pointCheckMapper.queryAuthorizeEnum(queryVo);
    }
}
